package ph.com.gs3.chat.fragments.worker;

import org.json.JSONException;
import org.json.JSONObject;

import ph.com.gs3.chat.communicators.AuthenticationCommunicatorModule;
import ph.com.gs3.chat.communicators.HttpCommunicator;
import ph.com.gs3.chat.communicators.HttpCommunicatorModule.CommunicatorException;
import ph.com.gs3.chat.model.valueobject.application.APIResponse;
import ph.com.gs3.chat.model.valueobject.application.APIResponse.APIInvalidResponseException;
import ph.com.gs3.chat.model.valueobject.application.APIResponse.APIStatus;
import ph.com.gs3.chat.model.valueobject.business.User;
import ph.com.gs3.chat.model.valueobject.business.User.UserParseException;
import ph.com.gs3.chat.utilities.FLLogger;
import ph.com.gs3.chat.utilities.FLLogger.LogType;
import android.app.Activity;
import android.app.Fragment;
import android.os.AsyncTask;

public class LoginWorkerFragment extends Fragment {

	public static final String TAG = LoginWorkerFragment.class.getSimpleName();

	private LoginWorkerListener listener;

	// required empty constructor
	public LoginWorkerFragment() {}

	private AuthenticationCommunicatorModule authenticationCommunicatorModule;

	// builder method
	public static LoginWorkerFragment createInstance() {

		LoginWorkerFragment instance = new LoginWorkerFragment();

		HttpCommunicator communicator = new HttpCommunicator();
		instance.authenticationCommunicatorModule = new AuthenticationCommunicatorModule(
		        communicator);

		return instance;

	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);

		try {
			listener = (LoginWorkerListener) activity;
		} catch (ClassCastException e) {
			throw new IllegalStateException(activity.getClass().getSimpleName()
			        + " must implement LoginViewActionListener");
		}
	}

	public void login(final String server, final String email, final String password) {

		authenticationCommunicatorModule.setServer(server);

		AsyncTask<Void, Void, LoginResult> loginAsyncTask = new AsyncTask<Void, Void, LoginResult>() {

			@Override
			protected LoginResult doInBackground(Void... params) {

				LoginResult loginResult = new LoginResult();
				loginResult.loginSuccess = false;

				// {{ Login with the communicator module
				APIResponse serverResponse;
				try {
					// throws CommunicatorException and/or APIResponseException
					authenticationCommunicatorModule.setServer(server);
					serverResponse = authenticationCommunicatorModule.login(email, password);

					FLLogger.d(TAG, "Server response on login: " + serverResponse.getResults());
				} catch (CommunicatorException e) {
					FLLogger.log(TAG + ", " + AuthenticationCommunicatorModule.TAG, LogType.ERROR,
					        e.getMessage());

					loginResult.message = "Connection Failed";
					return loginResult;
				} catch (APIInvalidResponseException e) {
					FLLogger.log(TAG + ", " + AuthenticationCommunicatorModule.TAG, LogType.ERROR,
					        e.getMessage());

					loginResult.message = e.getMessage();
					return loginResult;
				}

				// }}

				// {{ Checking server response on login
				if (serverResponse.getStatus() == APIStatus.SUCCESS) {

					String rawResults = serverResponse.getResults();
					// throws JSONException
					JSONObject rawResultsJSON;
					try {
						rawResultsJSON = new JSONObject(rawResults);
						User user = User.createFromJSON(rawResultsJSON, server);

						loginResult.loginSuccess = true;
						loginResult.user = user;

					} catch (JSONException | UserParseException e) {
						e.printStackTrace();
						loginResult.message = e.getMessage();
					}

				} else {
					loginResult.message = serverResponse.getErrorMessage();
				}

				// }}

				return loginResult;
			}

			@Override
			protected void onPostExecute(LoginResult result) {
				super.onPostExecute(result);

				if (result.loginSuccess) {
					listener.onLoginSuccess(result.user);
				} else {
					listener.onLoginFailed(result.message);
				}

			}

		};

		loginAsyncTask.execute();

		FLLogger.d(TAG, email + " is logging in");

	}

	public static class LoginResult {

		public boolean loginSuccess;
		public String message;
		public User user;

	}

	public static interface LoginWorkerListener {

		public void onLoginFailed(String message);

		public void onLoginSuccess(User loggedInUser);

	}

}
